// 解决嵌套问题
let activeEffect
const data = {name: '', age: 0}
const bucket = new WeakMap()
// 新增
let effectStack = []

// 收集依赖
function track (target, key) {
  let depsMap = bucket.get(target)
  if (!depsMap) {
    bucket.set(target, depsMap = new Map())
  }
  let deps = depsMap.get(key)
  if (!deps) {
    depsMap.set(key, deps = new Set())
  }
  if (activeEffect) {
    deps.add(activeEffect)
    activeEffect.deps.push(deps)
  }
}

// 触发事件
function trigger (target, key) {
  const depsMap = bucket.get(target)
  if (!depsMap) return
  const deps = depsMap.get(key)
  const effectsToRun = new Set(deps)
  effectsToRun.forEach(effect => effect())
}

// 代理
const obj = new Proxy(data, {
  get(target, key) {
    track(target, key)
    return target[key]
  },
  set(target, key, value) {
    target[key] = value
    trigger(target, key)
  }
})

function cleanup (effectFn) {
  for (let i = 0; i < effectFn.deps.length; i++) {
    const deps = effectFn.deps[i]
    deps.delete(effectFn)
  }
  effectFn.deps.length = 0
}

function effect (fn) {
  const effectFn = () => {
    cleanup(effectFn)
    // 照样还是赋值
    activeEffect = effectFn
    // ==== 新增
    // 将当前副作用函数存入栈中
    effectStack.push(effectFn)
    fn()
    // 执行后退掉栈
    effectStack.pop()
    // 将栈中前一个取出
    activeEffect = effectStack[effectStack.length - 1]
  }
  effectFn.deps = []
  effectFn()
}

let tmp1, tmp2
effect(() => {
  console.log('执行1')
  effect(() => {
    tmp2 = obj.name
    console.log('执行2')
  })
  tmp1 = obj.age
})

obj.age = '123'

/**
 * 解析:
 * 1. 修改的重点在副作用函数, 在执行回调之前, 将当前的副作用函数存入栈中
 * 2. 如果后续有内嵌方法, 则修改当前的activeEffect, 将新effect押入栈顶
 * 3. 内嵌方法执行完后, 执行pop, 再将上一个effect取出作为activeEffect
 */